home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / k053260.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  12KB  |  477 lines

  1. /*********************************************************
  2.  
  3.     Konami 053260 PCM Sound Chip
  4.  
  5. *********************************************************/
  6.  
  7. #include "driver.h"
  8. #include "k053260.h"
  9.  
  10. #define LOG 0
  11.  
  12. #define BASE_SHIFT    16
  13.  
  14. #define INTERPOLATE_SAMPLES 0
  15.  
  16. static struct K053260_channel_def {
  17.     unsigned long        rate;
  18.     unsigned long        size;
  19.     unsigned long        start;
  20.     unsigned long        bank;
  21.     unsigned long        volume;
  22.     int                    play;
  23.     unsigned long        pan;
  24.     unsigned long        pos;
  25. #if INTERPOLATE_SAMPLES
  26.     int                    steps;
  27.     int                    stepcount;
  28. #endif
  29.     int                    loop;
  30.     int                    ppcm; /* packed PCM ( 4 bit signed ) */
  31.     int                    ppcm_data;
  32. } K053260_channel[4];
  33.  
  34. static struct K053260_chip_def {
  35.     const struct K053260_interface    *intf;
  36.     int                                channel;
  37.     int                                mode;
  38.     int                                regs[0x30];
  39.     unsigned char                    *rom;
  40.     int                                rom_size;
  41.     void                            *timer; /* SH1 int timer */
  42. } K053260_chip;
  43.  
  44. static unsigned long *delta_table;
  45.  
  46. static void InitDeltaTable( void ) {
  47.     int        i;
  48.     double    base = ( double )Machine->sample_rate;
  49.     double    max = (double)K053260_chip.intf->clock; /* hz */
  50.     unsigned long val;
  51.  
  52.     for( i = 0; i < 0x1000; i++ ) {
  53.         double v = ( double )( 0x1000 - i );
  54.         double target = max / v;
  55.         double fixed = ( double )( 1 << BASE_SHIFT );
  56.  
  57.         if ( target && base ) {
  58.             target = fixed / ( base / target );
  59.             val = ( unsigned long )target;
  60.             if ( val == 0 )
  61.                 val = 1;
  62.         } else
  63.             val = 1;
  64.  
  65.         delta_table[i] = val;
  66.     }
  67. }
  68.  
  69. static void K053260_reset( void ) {
  70.     int i;
  71.  
  72.     for( i = 0; i < 4; i++ ) {
  73.         K053260_channel[i].rate = 0;
  74.         K053260_channel[i].size = 0;
  75.         K053260_channel[i].start = 0;
  76.         K053260_channel[i].bank = 0;
  77.         K053260_channel[i].volume = 0;
  78.         K053260_channel[i].play = 0;
  79.         K053260_channel[i].pan = 0;
  80.         K053260_channel[i].pos = 0;
  81.         K053260_channel[i].loop = 0;
  82.         K053260_channel[i].ppcm = 0;
  83.         K053260_channel[i].ppcm_data = 0;
  84.     }
  85. }
  86.  
  87. INLINE int limit( int val, int max, int min ) {
  88.     if ( val > max )
  89.         val = max;
  90.     else if ( val < min )
  91.         val = min;
  92.  
  93.     return val;
  94. }
  95.  
  96. #define MAXOUT 0x7fff
  97. #define MINOUT -0x8000
  98.  
  99. void K053260_update( int param, INT16 **buffer, int length ) {
  100.     static long dpcmcnv[] = { 0, 1, 4, 9, 16, 25, 36, 49, -64, -49, -36, -25, -16, -9, -4, -1 };
  101.  
  102.     int i, j, lvol[4], rvol[4], play[4], loop[4], ppcm_data[4], ppcm[4];
  103.     unsigned char *rom[4];
  104.     unsigned long delta[4], end[4], pos[4];
  105.     int dataL, dataR;
  106.     signed char d;
  107. #if INTERPOLATE_SAMPLES
  108.     int steps[4], stepcount[4];
  109. #endif
  110.  
  111.     /* precache some values */
  112.     for ( i = 0; i < 4; i++ ) {
  113.         rom[i]= &K053260_chip.rom[K053260_channel[i].start + ( K053260_channel[i].bank << 16 )];
  114.         delta[i] = delta_table[K053260_channel[i].rate];
  115.         lvol[i] = K053260_channel[i].volume * K053260_channel[i].pan;
  116.         rvol[i] = K053260_channel[i].volume * ( 8 - K053260_channel[i].pan );
  117.         end[i] = K053260_channel[i].size;
  118.         pos[i] = K053260_channel[i].pos;
  119.         play[i] = K053260_channel[i].play;
  120.         loop[i] = K053260_channel[i].loop;
  121.         ppcm[i] = K053260_channel[i].ppcm;
  122.         ppcm_data[i] = K053260_channel[i].ppcm_data;
  123. #if INTERPOLATE_SAMPLES
  124.         steps[i] = K053260_channel[i].steps;
  125.         stepcount[i] = K053260_channel[i].stepcount;
  126. #endif
  127.         if ( ppcm[i] ) {
  128.             delta[i] /= 2;
  129. #if INTERPOLATE_SAMPLES
  130.             steps[i] *= 2;
  131. #endif
  132.         }
  133.     }
  134.  
  135.         for ( j = 0; j < length; j++ ) {
  136.  
  137.             dataL = dataR = 0;
  138.  
  139.             for ( i = 0; i < 4; i++ ) {
  140.                 /* see if the voice is on */
  141.                 if ( play[i] ) {
  142.                     /* see if we're done */
  143.                     if ( ( pos[i] >> BASE_SHIFT ) >= end[i] ) {
  144.  
  145.                         ppcm_data[i] = 0;
  146.  
  147.                         if ( loop[i] )
  148.                             pos[i] = 0;
  149.                         else {
  150.                             play[i] = 0;
  151.                             continue;
  152.                         }
  153.                     }
  154.  
  155.                     if ( ppcm[i] ) { /* Packed PCM */
  156.                         /* we only update the signal if we're starting or a real sound sample has gone by */
  157.                         /* this is all due to the dynamic sample rate convertion */
  158.                         if ( pos[i] == 0 || ( ( pos[i] ^ ( pos[i] - delta[i] ) ) & 0x8000 ) == 0x8000 ) {
  159.                             int newdata;
  160.                             if ( pos[i] & 0x8000 )
  161.                                 newdata = rom[i][pos[i] >> BASE_SHIFT] & 0x0f;
  162.                             else
  163.                                 newdata = ( ( rom[i][pos[i] >> BASE_SHIFT] ) >> 4 ) & 0x0f;
  164.  
  165.                             ppcm_data[i] = ( ( ppcm_data[i] * 62 ) >> 6 ) + dpcmcnv[newdata];
  166.  
  167.                             if ( ppcm_data[i] > 127 )
  168.                                 ppcm_data[i] = 127;
  169.                             else
  170.                                 if ( ppcm_data[i] < -128 )
  171.                                     ppcm_data[i] = -128;
  172.                         }
  173.  
  174.                         d = ppcm_data[i];
  175.  
  176. //                        d /= 2;
  177.  
  178. #if INTERPOLATE_SAMPLES
  179.                         if ( steps[i] ) {
  180.                             if ( ( pos[i] >> BASE_SHIFT ) < ( end[i] - 1 ) ) {
  181.                                 signed char diff;
  182.                                 int next_d;
  183.  
  184.                                 if ( pos[i] & 0x8000 )
  185.                                     next_d = ( ( ( rom[i][(pos[i] >> BASE_SHIFT)+1] ) >> 4 ) & 0x0f ) * 0x11;
  186.                                 else
  187.                                     next_d = ( rom[i][( pos[i] >> BASE_SHIFT)] & 0x0f ) * 0x11;
  188.  
  189.                                 diff = next_d;
  190.                                 diff /= 2;
  191.                                 diff -= d;
  192.  
  193.                                 diff /= steps[i];
  194.  
  195.                                 d += ( diff * stepcount[i]++ );
  196.  
  197.                                 if ( stepcount[i] >= steps[i] )
  198.                                     stepcount[i] = 0;
  199.                             }
  200.                         }
  201. #endif
  202.                         pos[i] += delta[i];
  203.                     } else { /* PCM */
  204.                         d = rom[i][pos[i] >> BASE_SHIFT];
  205.  
  206. #if INTERPOLATE_SAMPLES
  207.                         if ( steps[i] ) {
  208.                             if ( ( pos[i] >> BASE_SHIFT ) < ( end[i] - 1 ) ) {
  209.                                 signed char diff = rom[i][(pos[i] >> BASE_SHIFT) + 1];
  210.                                 diff -= d;
  211.                                 diff /= steps[i];
  212.  
  213.                                 d += ( diff * stepcount[i]++ );
  214.  
  215.                                 if ( stepcount[i] >= steps[i] )
  216.                                     stepcount[i] = 0;
  217.                             }
  218.                         }
  219. #endif
  220.  
  221.                         pos[i] += delta[i];
  222.                     }
  223.  
  224.                     if ( K053260_chip.mode & 2 ) {
  225.                         dataL += ( d * lvol[i] ) >> 2;
  226.                         dataR += ( d * rvol[i] ) >> 2;
  227.                     }
  228.                 }
  229.             }
  230.  
  231.             buffer[1][j] = limit( dataL, MAXOUT, MINOUT );
  232.             buffer[0][j] = limit( dataR, MAXOUT, MINOUT );
  233.         }
  234.  
  235.     /* update the regs now */
  236.     for ( i = 0; i < 4; i++ ) {
  237.         K053260_channel[i].pos = pos[i];
  238.         K053260_channel[i].play = play[i];
  239.         K053260_channel[i].ppcm_data = ppcm_data[i];
  240. #if INTERPOLATE_SAMPLES
  241.         K053260_channel[i].stepcount = stepcount[i];
  242. #endif
  243.     }
  244. }
  245.  
  246. int K053260_sh_start(const struct MachineSound *msound) {
  247.     const char *names[2];
  248.     char ch_names[2][40];
  249.     int i;
  250.  
  251.     /* Initialize our chip structure */
  252.     K053260_chip.intf = msound->sound_interface;
  253.     K053260_chip.mode = 0;
  254.     K053260_chip.rom = memory_region(K053260_chip.intf->region);
  255.     K053260_chip.rom_size = memory_region_length(K053260_chip.intf->region) - 1;
  256.  
  257.     K053260_reset();
  258.  
  259.     for ( i = 0; i < 0x30; i++ )
  260.         K053260_chip.regs[i] = 0;
  261.  
  262.     delta_table = ( unsigned long * )malloc( 0x1000 * sizeof( unsigned long ) );
  263.  
  264.     if ( delta_table == 0 )
  265.         return -1;
  266.  
  267.     for ( i = 0; i < 2; i++ ) {
  268.         names[i] = ch_names[i];
  269.         sprintf(ch_names[i],"%s Ch %d",sound_name(msound),i);
  270.     }
  271.  
  272.     K053260_chip.channel = stream_init_multi( 2, names,
  273.                         K053260_chip.intf->mixing_level, Machine->sample_rate,
  274.                         0, K053260_update );
  275.  
  276.     InitDeltaTable();
  277.  
  278.     /* setup SH1 timer if necessary */
  279.     if ( K053260_chip.intf->irq )
  280.         K053260_chip.timer = timer_pulse( TIME_IN_HZ( ( K053260_chip.intf->clock / 32 ) ), 0, K053260_chip.intf->irq );
  281.     else
  282.         K053260_chip.timer = 0;
  283.  
  284.     return 0;
  285. }
  286.  
  287. void K053260_sh_stop( void ) {
  288.     if ( delta_table )
  289.         free( delta_table );
  290.  
  291.     delta_table = 0;
  292.  
  293.     if ( K053260_chip.timer )
  294.         timer_remove( K053260_chip.timer );
  295.  
  296.     K053260_chip.timer = 0;
  297. }
  298.  
  299. INLINE void check_bounds( int channel ) {
  300.     int channel_start = ( K053260_channel[channel].bank << 16 ) + K053260_channel[channel].start;
  301.     int channel_end = channel_start + K053260_channel[channel].size - 1;
  302.  
  303.     if ( channel_start > K053260_chip.rom_size ) {
  304.         logerror("K53260: Attempting to start playing past the end of the rom ( start = %06x, end = %06x ).\n", channel_start, channel_end );
  305.  
  306.         K053260_channel[channel].play = 0;
  307.  
  308.         return;
  309.     }
  310.  
  311.     if ( channel_end > K053260_chip.rom_size ) {
  312.         logerror("K53260: Attempting to play past the end of the rom ( start = %06x, end = %06x ).\n", channel_start, channel_end );
  313.  
  314.         K053260_channel[channel].size = K053260_chip.rom_size - channel_start;
  315.     }
  316. #if LOG
  317.     logerror("K053260: Sample Start = %06x, Sample End = %06x, Sample rate = %04lx, PPCM = %s\n", channel_start, channel_end, K053260_channel[channel].rate, K053260_channel[channel].ppcm ? "yes" : "no" );
  318. #endif
  319. }
  320.  
  321. WRITE_HANDLER( K053260_w )
  322. {
  323.     int i, t;
  324.     int r = offset;
  325.     int v = data;
  326.  
  327.     if ( r > 0x2f ) {
  328.         logerror("K053260: Writing past registers\n" );
  329.         return;
  330.     }
  331.  
  332.     if ( Machine->sample_rate != 0 )
  333.         stream_update( K053260_chip.channel, 0 );
  334.  
  335.     /* before we update the regs, we need to check for a latched reg */
  336.     if ( r == 0x28 ) {
  337.         t = K053260_chip.regs[r] ^ v;
  338.  
  339.         for ( i = 0; i < 4; i++ ) {
  340.             if ( t & ( 1 << i ) ) {
  341.                 if ( v & ( 1 << i ) ) {
  342.                     K053260_channel[i].play = 1;
  343.                     K053260_channel[i].pos = 0;
  344.                     K053260_channel[i].ppcm_data = 0;
  345.                     check_bounds( i );
  346. #if INTERPOLATE_SAMPLES
  347.                     if ( delta_table[K053260_channel[i].rate] < ( 1 << BASE_SHIFT ) )
  348.                         K053260_channel[i].steps = ( 1 << BASE_SHIFT ) / delta_table[K053260_channel[i].rate];
  349.                     else
  350.                         K053260_channel[i].steps = 0;
  351.                     K053260_channel[i].stepcount = 0;
  352. #endif
  353.                 } else
  354.                     K053260_channel[i].play = 0;
  355.             }
  356.         }
  357.  
  358.         K053260_chip.regs[r] = v;
  359.         return;
  360.     }
  361.  
  362.     /* update regs */
  363.     K053260_chip.regs[r] = v;
  364.  
  365.     /* communication registers */
  366.     if ( r < 8 )
  367.         return;
  368.  
  369.     /* channel setup */
  370.     if ( r < 0x28 ) {
  371.         int channel = ( r - 8 ) / 8;
  372.  
  373.         switch ( ( r - 8 ) & 0x07 ) {
  374.             case 0: /* sample rate low */
  375.                 K053260_channel[channel].rate &= 0x0f00;
  376.                 K053260_channel[channel].rate |= v;
  377.             break;
  378.  
  379.             case 1: /* sample rate high */
  380.                 K053260_channel[channel].rate &= 0x00ff;
  381.                 K053260_channel[channel].rate |= ( v & 0x0f ) << 8;
  382.             break;
  383.  
  384.             case 2: /* size low */
  385.                 K053260_channel[channel].size &= 0xff00;
  386.                 K053260_channel[channel].size |= v;
  387.             break;
  388.  
  389.             case 3: /* size high */
  390.                 K053260_channel[channel].size &= 0x00ff;
  391.                 K053260_channel[channel].size |= v << 8;
  392.             break;
  393.  
  394.             case 4: /* start low */
  395.                 K053260_channel[channel].start &= 0xff00;
  396.                 K053260_channel[channel].start |= v;
  397.             break;
  398.  
  399.             case 5: /* start high */
  400.                 K053260_channel[channel].start &= 0x00ff;
  401.                 K053260_channel[channel].start |= v << 8;
  402.             break;
  403.  
  404.             case 6: /* bank */
  405.                 K053260_channel[channel].bank = v & 0xff;
  406.             break;
  407.  
  408.             case 7: /* volume is 7 bits. Convert to 8 bits now. */
  409.                 K053260_channel[channel].volume = ( ( v & 0x7f ) << 1 ) | ( v & 1 );
  410.             break;
  411.         }
  412.  
  413.         return;
  414.     }
  415.  
  416.     switch( r ) {
  417.         case 0x2a: /* loop, ppcm */
  418.             for ( i = 0; i < 4; i++ )
  419.                 K053260_channel[i].loop = ( v & ( 1 << i ) ) != 0;
  420.  
  421.             for ( i = 4; i < 8; i++ )
  422.                 K053260_channel[i-4].ppcm = ( v & ( 1 << i ) ) != 0;
  423.         break;
  424.  
  425.         case 0x2c: /* pan */
  426.             K053260_channel[0].pan = v & 7;
  427.             K053260_channel[1].pan = ( v >> 3 ) & 7;
  428.         break;
  429.  
  430.         case 0x2d: /* more pan */
  431.             K053260_channel[2].pan = v & 7;
  432.             K053260_channel[3].pan = ( v >> 3 ) & 7;
  433.         break;
  434.  
  435.         case 0x2f: /* control */
  436.             K053260_chip.mode = v & 7;
  437.             /* bit 0 = read ROM */
  438.             /* bit 1 = enable sound output */
  439.             /* bit 2 = unknown */
  440.         break;
  441.     }
  442. }
  443.  
  444. READ_HANDLER( K053260_r )
  445. {
  446.     switch ( offset ) {
  447.         case 0x29: /* channel status */
  448.             {
  449.                 int i, status = 0;
  450.  
  451.                 for ( i = 0; i < 4; i++ )
  452.                     status |= K053260_channel[i].play << i;
  453.  
  454.                 return status;
  455.             }
  456.         break;
  457.  
  458.         case 0x2e: /* read rom */
  459.             if ( K053260_chip.mode & 1 ) {
  460.                 unsigned long offs = K053260_channel[0].start + ( K053260_channel[0].pos >> BASE_SHIFT ) + ( K053260_channel[0].bank << 16 );
  461.  
  462.                 K053260_channel[0].pos += ( 1 << 16 );
  463.  
  464.                 if ( offs > K053260_chip.rom_size ) {
  465.                     logerror("K53260: Attempting to read past rom size on rom Read Mode.\n" );
  466.  
  467.                     return 0;
  468.                 }
  469.  
  470.                 return K053260_chip.rom[offs];
  471.             }
  472.         break;
  473.     }
  474.  
  475.     return K053260_chip.regs[offset];
  476. }
  477.